# utils/task_service.py
import uuid
import logging
from typing import Dict, Any, Optional, List
from datetime import datetime, timedelta

from django.utils import timezone
from django.db import transaction

from app.models import ScheduledTask, TaskExecutionLog, TaskMetrics
from .scheduler_manager import SchedulerManager
from .task_executor import AsyncTaskExecutor

logger = logging.getLogger(__name__)


class TaskService:
    """任务管理服务"""
    
    def __init__(self):
        self.scheduler_manager = SchedulerManager()
        self.task_executor = AsyncTaskExecutor()
    
    def create_scheduled_task(self, 
                            name: str,
                            module_path: str,
                            function_name: str,
                            trigger_type: str,
                            trigger_config: Dict[str, Any],
                            description: str = "",
                            args: List = None,
                            kwargs: Dict = None,
                            max_instances: int = 1,
                            is_active: bool = True) -> ScheduledTask:
        """创建调度任务"""
        
        if args is None:
            args = []
        if kwargs is None:
            kwargs = {}
        
        # 生成唯一的 job_id
        job_id = f"task_{uuid.uuid4().hex[:8]}_{int(timezone.now().timestamp())}"
        
        with transaction.atomic():
            # 创建任务记录
            task = ScheduledTask.objects.create(
                name=name,
                description=description,
                module_path=module_path,
                function_name=function_name,
                args=args,
                kwargs=kwargs,
                trigger_type=trigger_type,
                trigger_config=trigger_config,
                is_active=is_active,
                max_instances=max_instances,
                job_id=job_id
            )
            
            # 创建统计记录
            TaskMetrics.objects.create(scheduled_task=task)
            
            # 如果任务激活且调度器运行中，添加到调度器
            if is_active and self.scheduler_manager.is_running:
                success = self.scheduler_manager.add_job_from_task(task)
                if not success:
                    logger.warning(f"任务创建成功但添加到调度器失败: {name}")
            
            logger.info(f"成功创建调度任务: {name} (ID: {task.id})")
            return task
    
    def update_scheduled_task(self, task_id: int, **kwargs) -> Optional[ScheduledTask]:
        """更新调度任务"""
        try:
            task = ScheduledTask.objects.get(id=task_id)
            
            # 记录原始状态
            was_active = task.is_active
            old_trigger_config = task.trigger_config.copy()
            
            # 更新字段
            for field, value in kwargs.items():
                if hasattr(task, field):
                    setattr(task, field, value)
            
            task.save()
            
            # 如果调度器正在运行，更新调度器中的任务
            if self.scheduler_manager.is_running:
                # 如果任务从激活变为非激活，移除任务
                if was_active and not task.is_active:
                    self.scheduler_manager.remove_job(task.job_id)
                
                # 如果任务激活且配置有变化，重新添加任务
                elif task.is_active and (
                    not was_active or 
                    old_trigger_config != task.trigger_config or
                    'trigger_type' in kwargs
                ):
                    self.scheduler_manager.add_job_from_task(task)
            
            logger.info(f"成功更新调度任务: {task.name}")
            return task
            
        except ScheduledTask.DoesNotExist:
            logger.error(f"任务不存在: {task_id}")
            return None
        except Exception as e:
            logger.error(f"更新任务失败 {task_id}: {e}")
            return None
    
    def delete_scheduled_task(self, task_id: int) -> bool:
        """删除调度任务"""
        try:
            task = ScheduledTask.objects.get(id=task_id)
            job_id = task.job_id
            
            # 从调度器中移除
            if self.scheduler_manager.is_running:
                self.scheduler_manager.remove_job(job_id)
            
            # 删除数据库记录
            task.delete()
            
            logger.info(f"成功删除调度任务: {job_id}")
            return True
            
        except ScheduledTask.DoesNotExist:
            logger.error(f"任务不存在: {task_id}")
            return False
        except Exception as e:
            logger.error(f"删除任务失败 {task_id}: {e}")
            return False
    
    def run_task_now(self, task_id: int) -> bool:
        """立即运行任务"""
        try:
            task = ScheduledTask.objects.get(id=task_id)
            
            if self.scheduler_manager.is_running:
                return self.scheduler_manager.run_job_now(task.job_id)
            else:
                logger.error("调度器未运行")
                return False
                
        except ScheduledTask.DoesNotExist:
            logger.error(f"任务不存在: {task_id}")
            return False
        except Exception as e:
            logger.error(f"立即运行任务失败 {task_id}: {e}")
            return False
    
    def pause_task(self, task_id: int) -> bool:
        """暂停任务"""
        try:
            task = ScheduledTask.objects.get(id=task_id)
            
            if self.scheduler_manager.is_running:
                return self.scheduler_manager.pause_job(task.job_id)
            else:
                # 如果调度器未运行，只更新数据库状态
                task.is_active = False
                task.save()
                return True
                
        except ScheduledTask.DoesNotExist:
            logger.error(f"任务不存在: {task_id}")
            return False
        except Exception as e:
            logger.error(f"暂停任务失败 {task_id}: {e}")
            return False
    
    def resume_task(self, task_id: int) -> bool:
        """恢复任务"""
        try:
            task = ScheduledTask.objects.get(id=task_id)
            
            if self.scheduler_manager.is_running:
                return self.scheduler_manager.resume_job(task.job_id)
            else:
                # 如果调度器未运行，只更新数据库状态
                task.is_active = True
                task.save()
                return True
                
        except ScheduledTask.DoesNotExist:
            logger.error(f"任务不存在: {task_id}")
            return False
        except Exception as e:
            logger.error(f"恢复任务失败 {task_id}: {e}")
            return False
    
    def get_task_logs(self, task_id: int, limit: int = 50) -> List[TaskExecutionLog]:
        """获取任务执行日志"""
        try:
            task = ScheduledTask.objects.get(id=task_id)
            return list(task.execution_logs.all()[:limit])
        except ScheduledTask.DoesNotExist:
            logger.error(f"任务不存在: {task_id}")
            return []
    
    def get_task_metrics(self, task_id: int) -> Optional[TaskMetrics]:
        """获取任务统计信息"""
        try:
            task = ScheduledTask.objects.get(id=task_id)
            metrics, created = TaskMetrics.objects.get_or_create(scheduled_task=task)
            if created or metrics.last_updated < timezone.now() - timedelta(minutes=5):
                metrics.update_metrics()
            return metrics
        except ScheduledTask.DoesNotExist:
            logger.error(f"任务不存在: {task_id}")
            return None
    
    def submit_async_task(self, 
                         strategy_id: str,
                         module_path: str,
                         function_name: str,
                         *args,
                         **kwargs) -> Optional[int]:
        """提交异步任务（非调度任务）"""
        try:
            # 动态导入函数
            import importlib
            module = importlib.import_module(module_path)
            func = getattr(module, function_name)
            
            # 提交到异步执行器
            task_id = self.task_executor.submit_task(strategy_id, func, *args, **kwargs)
            
            logger.info(f"成功提交异步任务: {strategy_id}, 任务ID: {task_id}")
            return task_id
            
        except Exception as e:
            logger.error(f"提交异步任务失败 {strategy_id}: {e}")
            return None
    
    def get_async_task_status(self, task_id: int) -> Dict[str, Any]:
        """获取异步任务状态"""
        return self.task_executor.get_task_status(task_id)
    
    def get_all_async_tasks(self) -> List[Dict[str, Any]]:
        """获取所有异步任务状态"""
        return list(self.task_executor.get_all_tasks())
    
    def create_interval_task(self, 
                           name: str,
                           module_path: str,
                           function_name: str,
                           seconds: int = 0,
                           minutes: int = 0,
                           hours: int = 0,
                           days: int = 0,
                           **kwargs) -> ScheduledTask:
        """创建间隔执行任务的便捷方法"""
        trigger_config = {
            'seconds': seconds,
            'minutes': minutes,
            'hours': hours,
            'days': days
        }
        
        return self.create_scheduled_task(
            name=name,
            module_path=module_path,
            function_name=function_name,
            trigger_type='interval',
            trigger_config=trigger_config,
            **kwargs
        )
    
    def create_cron_task(self,
                        name: str,
                        module_path: str,
                        function_name: str,
                        cron_expression: str = None,
                        **kwargs) -> ScheduledTask:
        """创建 Cron 任务的便捷方法"""
        if cron_expression:
            # 解析 cron 表达式
            parts = cron_expression.split()
            if len(parts) == 5:
                minute, hour, day, month, day_of_week = parts
                trigger_config = {
                    'minute': minute,
                    'hour': hour,
                    'day': day,
                    'month': month,
                    'day_of_week': day_of_week
                }
            else:
                raise ValueError("Cron 表达式格式错误，应为: 分 时 日 月 周")
        else:
            # 从 kwargs 中获取配置
            trigger_config = {
                key: kwargs.pop(key) for key in 
                ['second', 'minute', 'hour', 'day', 'month', 'day_of_week', 'week', 'year']
                if key in kwargs
            }
        
        return self.create_scheduled_task(
            name=name,
            module_path=module_path,
            function_name=function_name,
            trigger_type='cron',
            trigger_config=trigger_config,
            **kwargs
        )
    
    def create_date_task(self,
                        name: str,
                        module_path: str,
                        function_name: str,
                        run_date: datetime,
                        **kwargs) -> ScheduledTask:
        """创建定时执行任务的便捷方法"""
        trigger_config = {
            'run_date': run_date.isoformat()
        }
        
        return self.create_scheduled_task(
            name=name,
            module_path=module_path,
            function_name=function_name,
            trigger_type='date',
            trigger_config=trigger_config,
            **kwargs
        )